﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using API.Cryptsy.Entity;
using API.Cryptsy.Entity.Internal;
using System.Text.RegularExpressions;

namespace API.Cryptsy
{
    public partial class Cryptsy
    {

        public Order[] MyOrders(int marketid)
        {
            NameValueCollection args = new NameValueCollection();
            args["marketid"] = marketid.ToString();

            string s = API_POST_Query(PRIVATE_API_MYORDERS, args);

            SaveDebugInformation(args, s);

            Result<Order[]> result = _jsonSerializer.Deserialize(s, typeof(Result<Order[]>)) as Result<Order[]>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public Info GetInfo()
        {
            NameValueCollection args = new NameValueCollection();

            string s = API_POST_Query(PRIVATE_API_GETINFO, args);

            SaveDebugInformation(args, s);

            Result<Info> result = _jsonSerializer.Deserialize(s, typeof(Result<Info>)) as Result<Info>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public Market[] GetMarkets()
        {
            NameValueCollection args = new NameValueCollection();

            string s = API_POST_Query(PRIVATE_API_GETMARKETS, args);

            SaveDebugInformation(args, s);

            Result<Market[]> result = _jsonSerializer.Deserialize(s, typeof(Result<Market[]>)) as Result<Market[]>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public object GetWalletStatus()
        {
            NameValueCollection args = new NameValueCollection();

            string s = API_POST_Query(PRIVATE_API_GETWALLETSTATUS, args);

            SaveDebugInformation(args, s);

            Result<object> result = _jsonSerializer.Deserialize(s, typeof(Result<object>)) as Result<object>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public Transaction[] MyTransactions()
        {
            NameValueCollection args = new NameValueCollection();

            string s = API_POST_Query(PRIVATE_API_MYTRANSACTIONS, args);

            SaveDebugInformation(args, s);

            Result<Transaction[]> result = _jsonSerializer.Deserialize(s, typeof(Result<Transaction[]>)) as Result<Transaction[]>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }
 
        public Depth Depth(int marketid)
        {
            NameValueCollection args = new NameValueCollection();
            args["marketid"] = marketid.ToString();

            string s = API_POST_Query(PRIVATE_API_DEPTH, args);

            SaveDebugInformation(args, s);

            Result<Depth> result = _jsonSerializer.Deserialize(s, typeof(Result<Depth>)) as Result<Depth>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public object CancelOrder(long orderid)
        {
            NameValueCollection args = new NameValueCollection();
            args["orderid"] = orderid.ToString();

            string s = API_POST_Query(PRIVATE_API_CANCELORDER, args);

            SaveDebugInformation(args, s);

            Result<object> result = _jsonSerializer.Deserialize(s, typeof(Result<object>)) as Result<object>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public object GenerateNewAddress(int currencyid)
        {
            NameValueCollection args = new NameValueCollection();
            args["currencyid"] = currencyid.ToString();

            string s = API_POST_Query(PRIVATE_API_GENERATENEWADDRESS, args);

            SaveDebugInformation(args, s);

            Result<object> result = _jsonSerializer.Deserialize(s, typeof(Result<object>)) as Result<object>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public object GenerateNewAddress(string currencycode)
        {
            NameValueCollection args = new NameValueCollection();
            args["currencycode"] = currencycode;

            string s = API_POST_Query(PRIVATE_API_GENERATENEWADDRESS, args);

            SaveDebugInformation(args, s);

            Result<object> result = _jsonSerializer.Deserialize(s, typeof(Result<object>)) as Result<object>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public object MyTransfers()
        {
            NameValueCollection args = new NameValueCollection();

            string s = API_POST_Query(PRIVATE_API_MYTRANSFERS, args);

            SaveDebugInformation(args, s);

            Result<object> result = _jsonSerializer.Deserialize(s, typeof(Result<object>)) as Result<object>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public object MakeWithdrawal(string address, double amount)
        {
            NameValueCollection args = new NameValueCollection();
            args["address"] = address;
            args["amount"] = string.Format(DOUBLE_FORMAT, amount);

            string s = API_POST_Query(PRIVATE_API_MAKEWITHDRAWAL, args);

            SaveDebugInformation(args, s);

            Result<object> result = _jsonSerializer.Deserialize(s, typeof(Result<object>)) as Result<object>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        #region complete

        /// <summary>
        /// 2 Arrays. First array is sellorders listing current open sell orders ordered price ascending. Second array is buyorders listing current open buy orders ordered price descending. 
        /// </summary>
        /// <param name="marketid">Market ID for which you are querying</param>
        /// <returns>Returns listing current open sell orders ordered price ascending. Second array is buyorders listing current open buy orders ordered price descending.</returns>
        public MarketOrders MarketOrders(int marketid)
        {
            NameValueCollection args = new NameValueCollection();
            args["marketid"] = marketid.ToString();

            string s = API_POST_Query(PRIVATE_API_MARKETORDERS, args);

            //format the order data to fit class.
            s = s.Replace("\"sellprice\":", String.Format("\"marketid\":\"{0}\",\"ordertype\":\"sell\",\"price\":", marketid));
            s = s.Replace("\"buyprice\":", String.Format("\"marketid\":\"{0}\",\"ordertype\":\"buy\",\"price\":", marketid));

            SaveDebugInformation(args, s);

            Result<MarketOrders> result = _jsonSerializer.Deserialize(s, typeof(Result<MarketOrders>)) as Result<MarketOrders>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        /// <summary>
        /// Create a new Market Order
        /// </summary>
        /// <param name="marketId">Market ID for which you are creating an order for</param>
        /// <param name="orderType">Order type you are creating (Buy/Sell)</param>
        /// <param name="quantity">Amount of units you are buying/selling in this order</param>
        /// <param name="price">Price per unit you are buying/selling at</param>
        /// <returns>If successful, the Order ID for the order which was created</returns>
        public long CreateOrder(int marketId, OrderType orderType, double quantity, double price)
        {
            NameValueCollection args = new NameValueCollection();
            args["marketid"] = marketId.ToString();
            args["ordertype"] = orderType.ToString();
            args["quantity"] = string.Format(DOUBLE_FORMAT, quantity);
            args["price"] = string.Format(DOUBLE_FORMAT, price);

            string s = API_POST_Query(PRIVATE_API_CREATEORDER, args);

            SaveDebugInformation(args, s);

            NewOrder result = _jsonSerializer.Deserialize(s, typeof(NewOrder)) as NewOrder;
            if (result.Success == 1)
                return result.OrderID;
            else
                throw new Exception(result.Error);
        }

        /// <summary>
        /// Retrive all deposit addresses associate with the account
        /// </summary>
        /// <returns>Returns a collection of currency codes and corresponding deposit addresses</returns>
        public NameValueCollection GetMyDepositAddresses()
        {
            NameValueCollection args = new NameValueCollection();

            string s = API_POST_Query(PRIVATE_API_GETMYDEPOSITADDRESSES, args);

            SaveDebugInformation(args, s);

            Result<NameValueCollection> result = _jsonSerializer.Deserialize(s, typeof(Result<NameValueCollection>)) as Result<NameValueCollection>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        /// <summary>
        /// Calculate the fees for the specified transaction
        /// </summary>
        /// <param name="orderType">Order type you are calculating for (Buy/Sell)</param>
        /// <param name="quantity">Amount of units you are buying/selling</param>
        /// <param name="price">Price per unit you are buying/selling at</param>
        /// <returns>Return what would be charged for provided inputs and the net total with fees</returns>
        public Fees CalculateFees(OrderType orderType, double quantity, double price)
        {
            NameValueCollection args = new NameValueCollection();
            args["ordertype"] = orderType.ToString();
            args["quantity"] = string.Format(DOUBLE_FORMAT, quantity);
            args["price"] = string.Format(DOUBLE_FORMAT, price);

            string s = API_POST_Query(PRIVATE_API_CALCULATEFEES, args);

            SaveDebugInformation(args, s);

            Result<Fees> result = _jsonSerializer.Deserialize(s, typeof(Result<Fees>)) as Result<Fees>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        /// <summary>
        /// Cancels all open orders
        /// </summary>
        /// <returns>Returns a list of canceled orders</returns>
        public long[] CancelAllOrders()
        {
            NameValueCollection args = new NameValueCollection();

            string s = API_POST_Query(PRIVATE_API_CANCELALLORDERS, args);

            SaveDebugInformation(args, s);

            Result<string[]> result = _jsonSerializer.Deserialize(s, typeof(Result<string[]>)) as Result<string[]>;
            if (result.Success == 1)
            {
                List<long> orderNumbers = new List<long>();
                foreach (string order in result.Return)
                {
                    long number = long.Parse(Regex.Replace(order, @"[^\d]", ""));
                    orderNumbers.Add(number);
                }
                return orderNumbers.ToArray();
            }
            else
                throw new Exception(result.Error);
        }

        /// <summary>
        /// Cancels all open orders for the specified market
        /// </summary>
        /// <param name="marketid">Market ID for which you would like to cancel all open orders</param>
        /// <returns>A list of all closed market orders</returns>
        public long[] CancelMarketOrders(int marketid)
        {
            NameValueCollection args = new NameValueCollection();
            args["marketid"] = marketid.ToString();

            string s = API_POST_Query(PRIVATE_API_CANCELMARKETORDERS, args);

            SaveDebugInformation(args, s);

            Result<string[]> result = _jsonSerializer.Deserialize(s, typeof(Result<string[]>)) as Result<string[]>;
            if (result.Success == 1)
            {
                List<long> orderNumbers = new List<long>();
                foreach (string order in result.Return)
                {
                    long number = long.Parse(Regex.Replace(order, @"[^\d]", ""));
                    orderNumbers.Add(number);
                }
                return orderNumbers.ToArray();
            }
            else
                throw new Exception(result.Error);
        }

        /// <summary>
        /// Retrieve all open orders
        /// </summary>
        /// <returns>Returns an array of all open orders for your account</returns>
        public Order[] AllMyOrders()
        {
            NameValueCollection args = new NameValueCollection();

            string s = API_POST_Query(PRIVATE_API_ALLMYORDERS, args);

            SaveDebugInformation(args, s);

            Result<Order[]> result = _jsonSerializer.Deserialize(s, typeof(Result<Order[]>)) as Result<Order[]>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public Trade[] MyTrades(int marketid)
        {
            NameValueCollection args = new NameValueCollection();
            args["marketid"] = marketid.ToString();

            string s = API_POST_Query(PRIVATE_API_MYTRADES, args);

            SaveDebugInformation(args, s);

            Result<Trade[]> result = _jsonSerializer.Deserialize(s, typeof(Result<Trade[]>)) as Result<Trade[]>;
            if (result.Success == 1)
            {
                foreach (Trade t in result.Return)
                    t.MarketID = marketid;
                return result.Return;
            }
            else
                throw new Exception(result.Error);
        }

        public Trade[] MyTrades(int marketid, uint limit)
        {
            NameValueCollection args = new NameValueCollection();
            args["marketid"] = marketid.ToString();
            args["limit"] = limit.ToString();

            string s = API_POST_Query(PRIVATE_API_MYTRADES, args);

            SaveDebugInformation(args, s);

            Result<Trade[]> result = _jsonSerializer.Deserialize(s, typeof(Result<Trade[]>)) as Result<Trade[]>;
            if (result.Success == 1)
            {
                foreach (Trade t in result.Return)
                    t.MarketID = marketid;
                return result.Return;
            }
            else
                throw new Exception(result.Error);
        }

        public Trade[] AllMyTrades()
        {
            NameValueCollection args = new NameValueCollection();

            string s = API_POST_Query(PRIVATE_API_ALLMYTRADES, args);

            SaveDebugInformation(args, s);

            Result<Trade[]> result = _jsonSerializer.Deserialize(s, typeof(Result<Trade[]>)) as Result<Trade[]>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public Trade[] AllMyTrades(DateTime startDate, DateTime endDate)
        {
            NameValueCollection args = new NameValueCollection();
            args["startdate"] = startDate.ToString("yyyy-MM-dd");
            args["enddate"] = endDate.ToString("yyyy-MM-dd");

            string s = API_POST_Query(PRIVATE_API_ALLMYTRADES, args);

            SaveDebugInformation(args, s);

            Result<Trade[]> result = _jsonSerializer.Deserialize(s, typeof(Result<Trade[]>)) as Result<Trade[]>;
            if (result.Success == 1)
                return result.Return;
            else
                throw new Exception(result.Error);
        }

        public Trade[] MarketTrades(int marketid)
        {
            NameValueCollection args = new NameValueCollection();
            args["marketid"] = marketid.ToString();

            string s = API_POST_Query(PRIVATE_API_MARKETTRADES, args);

            SaveDebugInformation(args, s);

            Result<Trade[]> result = _jsonSerializer.Deserialize(s, typeof(Result<Trade[]>)) as Result<Trade[]>;
            if (result.Success == 1)
            {
                foreach (Trade t in result.Return)
                    t.MarketID = marketid;
                return result.Return;
            }
            else
                throw new Exception(result.Error);
        }

        #endregion
    }
}
